/**
 * 从这里开始，算是高级类型的范围
 * 高级内容有内容:
 * 1.newtype模式(新类型模式)
 *   a.用于抽象掉一些类型的实现细节
 *   b.可以隐藏其内部的泛型类型
 * 大体上可以理解为这是一种封装，封装可能的效果就是新类型的效果。
 * 没有太多可以讨论和思考的.
 * 2.类型别名(type alias)
 * 类型别名看起来很像sqlserver的别名，二者本质上起到的作用是一样的：
 *   a.简化类型书写
 *   b.使得代码更容易阅读
 *   c.也更方便维护,例如如果许多方法都要求用同个类型，那么这样定义之后就不容易搞错，
 *     作用上和java中定义的枚举常量一个道理。
 * 在rust的标准库中，有不少的类型别名，例如Option<T>和Result<T,E>等。
 * 3.never类型(empty 类型)
 * 4.动态大小类型和Sized特质
 * 本文先讨论1，2两点
 */

//定义类型别名Thunk，它是一个闭包类型,表达这样一个意思:
// 这是一个可以发送的，静态生命周期的闭包类型（不接收参数)。

struct Person {
    name: String,
    age: u8,
}
type Teacher = Person;
type Student = Person;
type GoodPeople = Student;
type Thunk = Box<dyn Fn() + Send + 'static>;

fn print_student(p: &Student) {
    println!("name={},age={}", p.name, p.age);
}

fn print_me(p: &GoodPeople) {
    println!("name={},age={}", p.name, p.age);
}

fn main() {
    let f: Thunk = Box::new(|| println!("hi"));
    //应为Thunk是Box类型，已经实现了Deref特质，它可以自动解引用，所以可以直接调用。
    f();
    //如果想显式调用，可以这样写：
    (*f)();
    let p = Student {
        name: "张三".to_string(),
        age: 30,
    };
    print_student(&p);

    let g = GoodPeople {
        name: "lzf".to_string(),
        age: 99,
    };
    print_me(&g);
}
#[allow(unused)]
fn takes_long_type(f: Thunk) {
    // --snip--
}
#[allow(unused)]
fn returns_long_type() -> Thunk {
    // --snip--
    Box::new(|| {})
}
